--[[
   10.0.29.66:30066 通过soap传输的二代支付应用报文
   10.0.29.67:30066 通过soap传输的二代支付应用报文
F5-10.0.29.68:30066 通过soap传输的二代支付应用报文
]]
require("apm_core")
require("ApmXml")

local G_DEBUG = false

if G_DEBUG == false then
    function logDebug(fmt,...) end
    function logInfo(fmt,...) end
    function logWarn(fmt,...) end
    function logError(fmt,...) end
    function logFatal(fmt,...) end
end

local KRED='\x1B[0;31m'
local KSALMON='\x1B[1;31m'
local KGREEN='\x1B[0;32m'
local KLIMEGREEN='\x1B[1;32m'
local KYELLOW='\x1B[0;33m'
local KORANGE='\x1B[0;34m'
local KBLUE='\x1B[1;34m'
local KMAGENTA='\x1B[0;35m'
local KPINK='\x1B[1;35m'
local KCYAN='\x1B[0;36m'
local RESET='\x1B[0m'

local t_xml_tree
local s_businessAcceptId
local s_transcode
local s_transcode_name
local s_rspcode
local s_rspmsg

local t_transcode = {
    ["961009"] = "二代支付大额贷记往账",
	["961003"] = "二代支付大额贷记往账复核",
	["961305"] = "二代支付小额贷记往账复核",
	["960631"] = "发出二代支付查询报文",
	["960634"] = "发出二代支付查复报文",
	["960625"] = "发出二代支付自由格式",
	["960629"] = "发出二代支付业务撤销申请",
	["960635"] = "发出二代支付业务退回申请",
	["960627"] = "发出二代支付业务状态查询",
	["969900"] = "二代支付来账挂账处理",
	["961005"] = "取消二代支付大额贷记往账业务",
	["961304"] = "取消二代支付小额贷记往账业务",
	["961009"] = "资金调拨录入",
	["961003"] = "资金调拨审批",
	["961009"] = "OPICS录入",
	["961003"] = "OPICS复核发送",
	["969901"] = "重起PE流程",
	["969800"] = "更改查询查复打印次数",
	["969807"] = "支付系统机构维护",
	["961381"] = "二代支付小额实时通存往账",
	["961391"] = "二代支付小额实时通兑往账",
	["961421"] = "二代支付小额实时通存通兑协议维护",
	["961301"] = "二代支付小额普通贷记往帐",
	["961320"] = "发出小额普通借记",
	["961441"] = "发出小额定期贷记",
	["961461"] = "发出小额定期借记",
	["961565"] = "发出客户账户实时查询",
	["961569"] = "发出借记业务止付申请",
	["961424"] = "发出实时业务冲正",
	["961320"] = "发出小额支票截留",
	["961391"] = "发出小额解付他行本汇票",
	["961572"] = "发出借记止付申请应答",
	["960638"] = "发出退回申请应答",
	["969501"] = "小额定期信息维护",
	["969503"] = "代收付协议管理",
	["961326"] = "发送小额普通借记回执",
	["961541"] = "主动缴费查询",
	["961543"] = "主动缴费通知",
	["961364"] = "票交回执往账录入",
	["969400"] = "小额实时业务调账",
	["969007"] = "支付系统往账异常调账",
	["969300"] = "小额普通业务被拒绝包处理",
	["969305"] = "发送支票截留回执",
	["961594"] = "支付系统业务补录",
	["969903"] = "资金调拨参数维护",
	["969909"] = "支付系统来账异常调账",
	["969910"] = "更改支付系统来账状态",
	["969911"] = "处理批量转账业务",
	["969912"] = "处理支付系统批量审核",
	["969916"] = "网银查询支付流水",
	["969918"] = "支付系统健康检查",
	["969011"] = "发出跨境支付退汇",
	["969922"] = "修改二代支付参数",
	["969923"] = "实时借记来账恢复本汇票状态",
	["969926"] = "登记客户信息查询往账",
	["969927"] = "客户信息查询相关参数修改",
	["969802"] = "二代支付行名行号查询",
	["969801"] = "二代支付查询查复查询打印",
	["969404"] = "二代支付通存通兑查询",
	["969003"] = "即时转账报文查询",
	["969001"] = "大额往账支付信息查询",
	["969002"] = "大额来账支付信息查询",
	["969500"] = "小额批量包查询",
	["969301"] = "小额借记回执包明细查询",
	["969004"] = "资金调拨参数查询",
	["969600"] = "小额轧差清算登记簿查询",
	["969302"] = "小额支付信息查询",
	["969803"] = "撤销登记簿查询",
	["969804"] = "退回登记簿查询",
	["969401"] = "冲正登记簿查询",
	["969303"] = "止付登记簿查询",
	["969402"] = "通存通兑协议查询",
	["969005"] = "大额汇总对账数据查询",
	["969304"] = "小额汇总对账数据查询",
	["969403"] = "小额本汇票解付报文查询",
	["969006"] = "资金调拨登记簿查询",
	["969805"] = "查询查复辅助信息查询",
	["969008"] = "大额明细对账数据查询",
	["969502"] = "小额明细对账数据查询",
	["969905"] = "小额行内应清算记录查询",
	["969906"] = "小额行内待确认记录查询",
	["969907"] = "小额隔日待确认记录查询",
	["969806"] = "支付系统状态查询",
	["969908"] = "资金系统对账查询",
	["969904"] = "支付系统自助渠道转账结果查询",
	["969504"] = "支付系统异常登记簿查询",
	["969505"] = "代收付业务汇总查询",
	["969506"] = "代收付业务明细查询",
	["969306"] = "查询小额普通借记票据业务",
	["969009"] = "获取OPICS往账记录",
	["969010"] = "获取预签电子银行汇票记录",
	["969913"] = "获取支付系统待复核记录",
	["969914"] = "获取支付系统对账报文状态",
	["969915"] = "校验支付系统抹账状态",
	["969917"] = "获取小额清算数据",
	["969919"] = "查询支付系统起流程记录",
	["969012"] = "查询华东三省一市汇票多余款记录",
	["969920"] = "查询二代支付参数",
	["969921"] = "查询二代支付流程列表信息",
	["969013"] = "获取大额跨境业务附加信息",
	["969014"] = "跨境业务信息查询",
}

local function parseIp(ip)
    local _, _, value = string.find(ip, "(%d+.%d+)$")
    return value == nil and "" or value
end

--- 协议判断
-- return
-- true; false
local function protocol_detect(s_payload)
    if s_payload == nil then return false end

    t_xml_tree = ApmXml.load(s_payload, "UTF-8")

    if t_xml_tree == nil then return false end

    return ApmXml.getValue(t_xml_tree, "/soapenv:Envelope") ~= nil or
		   ApmXml.getValue(t_xml_tree, "/SOAP-ENV:Envelope") ~= nil or
		   ApmXml.getValue(t_xml_tree, "/e:Envelope") ~= nil
end

--- 解析请求
-- return
-- true: 解析成功; false: 解析失败
local function parse_request(ApmData)
    s_businessAcceptId = ApmXml.getValue(t_xml_tree, ".//requestHeader/businessAcceptId/text()")
    s_transcode = ApmXml.getValue(t_xml_tree, ".//transcode/text()")
	if s_transcode ~= nil then
		s_transcode_name = t_transcode[s_transcode]
		if s_transcode_name == nil then s_transcode_name = s_transcode end
	end
    return true
end

--- 解析响应
-- return
-- true: 解析成功; false: 解析失败
local function parse_response(ApmData)
    -- 交易返回代码
    s_rspcode = ApmXml.getValue(t_xml_tree, ".//responseHeader/errorNo/text()")
	
    -- 交易返回信息
    s_rspmsg = ApmXml.getValue(t_xml_tree, ".//responseHeader/errorInfo/text()")
    if s_rspmsg ~= nil then
        s_rspmsg = string.trim(s_rspmsg)
    end

    return true
end

--- main
function post_analysis()
    local ApmData = require("ApmData")
    if ApmData.getL7Proto() ~= 80 then return end
    if ApmData.getMsgType() ~= 1 then return end

    local s_soap_req
    local s_soap_resp

    s_soap_req = ApmData.getField("request.http.body.1", 1)
    if s_soap_req ~= nil then
        s_soap_req = string.trim(s_soap_req)
        if protocol_detect(s_soap_req) then
            parse_request(ApmData)
        else
			logInfo("Request:["..KRED.."%s"..RESET.."]", s_soap_req)
		end
    end

    s_soap_resp = ApmData.getField("response.http.body.1", 1)
    if s_soap_resp ~= nil then
        s_soap_resp = string.trim(s_soap_resp)
        if protocol_detect(s_soap_resp) then
            parse_response(ApmData)
		else
			logInfo("Response:["..KBLUE.."%s"..RESET.."]", s_soap_resp)
        end
    end
	
	if s_transcode == nil then
        logInfo("s_transcode is nil REQ:[%s]", s_soap_req)
    elseif s_rspcode == nil then
        logInfo("s_rspcode is nil RESP:[%s]", s_soap_resp)
    else
        ApmData.replaceField("transaction.type_code", s_transcode)
        ApmData.replaceField("transaction.type_name", s_transcode_name)
        --ApmData.replaceField("transaction.title", s_transcode_name)

        ApmData.replaceField("response.code_string", s_rspcode)
        ApmData.delFields("response.code")

        if s_rspmsg ~= nil then
            ApmData.replaceField("response.error_message", s_rspmsg)
        end

        if s_businessAcceptId ~= nil then
            ApmData.replaceField("transaction.code", s_businessAcceptId)
        end

        logInfo("CNAPS2 APP(%s:%d->%s:%d) transcode:%s|name:%s|seq:%s|ret:%s|%s",
            ApmData.getSrcIp(),
            ApmData.getSrcPort(),
            parseIp(ApmData.getDstIp()),
            ApmData.getDstPort(),
            s_transcode,
            s_transcode_name,
            s_businessAcceptId,
            s_rspcode,
            s_rspmsg
        )
    end
	
    return
end
--二代支付IFW
--v1.0.1
